package cat.joronya.supermanager.service.htmlcleanerImpl;

import java.text.NumberFormat;
import java.text.ParseException;
import java.util.List;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.htmlcleaner.ContentNode;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;

import android.util.Log;
import cat.joronya.supermanager.Supermanager;
import cat.joronya.supermanager.market.Player;
import cat.joronya.supermanager.service.MyTeamDetailParser;
import cat.joronya.supermanager.team.Team;

public class MyTeamDetailParserImpl implements MyTeamDetailParser 
{
	protected Team team;
	
	// jornada XPATH
	private static final String DAY_XPATH = "//font[@class='naranja15']";
	
	// anular cambios XPATH
	//private static final String CANCEL_CHANGES_XPATH = "//input[@value='ANULAR CAMBIOS REALIZADOS']";
	private static final String CANCEL_CHANGES_XPATH = "//td[@class='letranegra']"; 
	
	// team name XPATH
	private static final String TEAM_NAME_XPATH = "//td[@class='letrablanca']";
	
	// team cash XPATH
	private static final String TEAM_CASH_XPATH = "//td[@background='gif/tablaarribanegro2.gif']";
	
	// team players XPATH
	private static final String TEAM_PLAYERS_XPATH = "//td[@class='titulonegroi']";
	
	// team extra details javascript XPATH
	private static final String TEAM_JAVASCRIPT_XPATH = "//script[@language='JavaScript']";
	
	// jornada your week XPATH
	private static final String YOUR_WEEK_DAY_XPATH = "//td[@class='verequipo_peq_arriba']";
	
	public Team getTeam() 
	{
		return team;
	}

	public long parse(String idequ, String html) throws Exception 
	{
		long start = System.nanoTime();
		
		team = new Team();
		team.setIdEqu(idequ);
		
		HtmlCleaner cleaner = new HtmlCleaner();
		TagNode node = cleaner.clean(html);

		NumberFormat nf = NumberFormat.getInstance(new Locale("es","ES"));
	
		// cerquem la jornada
		Integer day = Integer.valueOf("0");
		
		Object[] fontsJornada = node.evaluateXPath(DAY_XPATH);
		TagNode fontJornada = (TagNode)fontsJornada[0];
		for( Object fontContent: fontJornada.getChildren() )
		{
			if( fontContent instanceof ContentNode )
			{
				String jornada = fontContent.toString();
				jornada = jornada.replace("Jornada ", "");
				day = Integer.valueOf("0");
				try{
					day = Integer.parseInt(jornada);
				}catch(NumberFormatException nfe){
					day = Integer.valueOf("0");
				}
				team.setDay(day);
			}
		}
		Log.d(Supermanager.TAG,"MyTeamDetailParser parser found day: "+day);
		
		// cerquem el nom de l'equip
		String name = "";
		
		Object[] tdsName = node.evaluateXPath(TEAM_NAME_XPATH);
		TagNode tdName = (TagNode)tdsName[0];
		for( Object tdContent: tdName.getChildren() )
		{
			if( tdContent instanceof ContentNode )
			{
				String tmpName = tdContent.toString();
				if( tmpName.startsWith("\nEquipo: ") )
					name = tmpName.replace("\nEquipo: ", "");
			}
		}
		team.setName(name);
		Log.d(Supermanager.TAG,"MyTeamDetailParser parser found name: "+name);
		
		// cerquem el cash
        Object[] tdsCash = node.evaluateXPath(TEAM_CASH_XPATH);
        TagNode cashTd = (TagNode)tdsCash[1];
        for( Object cashContent: cashTd.getChildren() )
		{
			if( cashContent instanceof ContentNode )
			{
				Integer cash = Integer.valueOf("0");
				try{
					cash = Integer.valueOf(nf.parse(cashContent.toString().trim()).intValue());
   				}catch(ParseException pe){
   					cash = Integer.valueOf("0");
   				}
   				// ho fiquem al arg, per guardar amb dades 
   				team.setCash(cash);
			}
		}
        
        // cerquem cancelar canvis, i canvis fets
        Object[] inputCancelChanges = node.evaluateXPath(CANCEL_CHANGES_XPATH);
        if( inputCancelChanges.length > 0 )
        {
        	List ccChilds = ((TagNode)inputCancelChanges[0]).getChildren();
        	for (Object ccChild: ccChilds) 
        	{
				if( ccChild instanceof TagNode )
				{
					TagNode ccNode = (TagNode)ccChild;
					if( "b".equals(ccNode.getName()) )
					{
						List ccContentNodes = ccNode.getChildren();
						if( ccContentNodes.size() > 0 )
						{
							int changesDone = Integer.parseInt(((ContentNode)ccContentNodes.get(0)).toString());
							team.setChangesDone(changesDone);
							// TODO: com saber quants canvis hi ha?
							team.setChangesTotal(3);
						}
					}
					if( "input".equals(ccNode.getName()) )
					{
			        	team.setCancelChanges(1);
					}
				}
			}
        }
        
        // cerquem your week day
        Object[] yourWeekTds = node.evaluateXPath(YOUR_WEEK_DAY_XPATH);
        if( yourWeekTds.length > 0 )
        {
        	TagNode yourWeekTd = (TagNode)yourWeekTds[0];
        	for( Object yourWeekChild: yourWeekTd.getChildren() )
        	{
        		if( yourWeekChild instanceof ContentNode )
        			continue;
        	
        		TagNode yourWeekSpan = (TagNode)yourWeekChild;
        		if( !"span".equals(yourWeekSpan.getName()) )
        			continue;
        	
        		Integer yourWeekDay = 0;
        		try
        		{
        			String yourWeekString = yourWeekSpan.getChildren().get(0).toString();
        			yourWeekString = yourWeekString.replace("&ordf; jornada", "");
        			yourWeekDay = Integer.valueOf(yourWeekString);
        		}
        		catch(Exception e){}

        		Log.d(Supermanager.TAG,"MyTeamDetailParser yourWeekDay: "+yourWeekDay);
        		team.setYourWeekDay(yourWeekDay);
        	}
        
        	// cerquem ganancies/perdues
        	TagNode yourWeekTbody = yourWeekTd.getParent().getParent();
        	List yourWeeksTrs = yourWeekTbody.getChildren();
        	TagNode guanysTr = (TagNode)yourWeeksTrs.get(5);
        	List guanysTds = guanysTr.getChildren();
        	TagNode guanysValueTd = (TagNode)guanysTds.get(1);
        	for( Object guanysContentNode: guanysValueTd.getChildren() )
        	{
        		if( guanysContentNode instanceof ContentNode )
        		{
        			String guanysString = guanysContentNode.toString();
        			guanysString = guanysString.replace("+", "");
        			Integer guanys = Integer.valueOf(0);
        			try{
        				guanys = Integer.valueOf(nf.parse(guanysString).intValue());
        			}catch(ParseException pe){
        				guanys = Integer.valueOf(0);
        			}
   				
        			Log.d(Supermanager.TAG,"MyTeamDetailParser guanys: "+guanys);
        			team.setEarnings(guanys);
        		}
        	}
        }
        
        // llistat de jugadors
        Object[] tdHeaderPlayers = node.evaluateXPath(TEAM_PLAYERS_XPATH);
        TagNode[] trsPlayers = ((TagNode)tdHeaderPlayers[0]).getParent().getParent().getChildTags();
        int position = -1;
        for( TagNode trPlayer: trsPlayers )
        {
        	position++;
        	TagNode[] tds = trPlayer.getChildTags();
        	
        	// td0, saltem el primer tr dels titular
        	if( "titulonegroi".equals(tds[0].getAttributeByName("class")) )
        		continue;
        	
        	// saltem l'ultim tr del peu
        	if( "gif/fondotablaabajoizquierdaarriba.gif".equals(tds[0].getAttributeByName("background")) )
        		continue;
        	
        	// mirem el rowspan
        	int rowspan = ("3".equals(tds[0].getAttributeByName("rowspan")) 
        			|| "4".equals(tds[0].getAttributeByName("rowspan")))?1:0;
        	
        	// inicialitzem jugador
        	Player player = new Player();
        	// als players fiquem day parsejat aqui
        	player.setDay(day);
        	player.setPosition(position+"");
        	player.setTeamPositionByIndex(position);
        	
        	// td1, fitxa lliure?
        	try{
        		TagNode fitxaLliure = tds[0+rowspan];//.getChildTags()[0];
        		if( "10".equals(fitxaLliure.getAttributeByName("colspan")) )
        		{
        			// buy de les fitxes lliures
        			TagNode botoTd = tds[1+rowspan];
        			TagNode botoAnchor = botoTd.getChildTags()[0];
        			TagNode botoImg = botoAnchor.getChildTags()[0];
        			if( "img".equals(botoImg.getName()) )
        			{
        				if( "gif/fichar.gif".equals(botoImg.getAttributeByName("src")) )
        					player.setBuy(true);
        			}

        			// anular de les fitxes lliures
        			TagNode botoTd2 = tds[2+rowspan];
        			TagNode botoAnchor2 = botoTd2.getChildTags()[0];
        			TagNode botoImg2 = botoAnchor2.getChildTags()[0];
        			if( "img".equals(botoImg2.getName()) )
        			{
        				if( "gif/anular.gif".equals(botoImg2.getAttributeByName("src")) )
        					player.setCancel(true);
        			}
        			
        			// afegim el player a l'equip
                	team.addPlayer(position,player);
                	
        			// if free card, nothing more to parse
        			continue;
        		}
        	}
        	catch(Exception e){}
        	
        	// sell dels altres
        	try{
        		// sell, cancel dels altres
    			TagNode botoAnchor = tds[10+rowspan].getChildTags()[0];
    			if( "a".equals(botoAnchor.getName()) )
    			{
    				if( botoAnchor.getAttributeByName("onclick").startsWith("comprueba2") )
    				{	
    					player.setSell(true);
    				}
    				else if( botoAnchor.getAttributeByName("onclick").startsWith("comprueba4") )
    				{
    					player.setSell(true);
    					player.setChange(true);
    				}
    			}
        	}
        	catch(Exception e){}
    		
        	// cancel dels altres
        	try{
    			TagNode botoAnchor2 = tds[11+rowspan].getChildTags()[0];
    			if( "a".equals(botoAnchor2.getName()) )
    			{
    				if( botoAnchor2.getAttributeByName("onclick").startsWith("comprueba3") )
    				{	
    					player.setCancel(true);
    				}
    			}
        	}
        	catch(Exception e){}
        	
        	// td0, status: parse lesionat/semafor
        	try{
        		TagNode imgStatus2 = tds[0+rowspan].getChildTags()[0];
        		if( "gif/lesion.gif".equals(imgStatus2.getAttributeByName("src")) )
        			player.setStatus("lesio.png");
        		if( "gif/baja.gif".equals(imgStatus2.getAttributeByName("src")) )
        			player.setStatus("baixa.png");
        	}
        	catch(Exception e){}
        	
        	// td1, nationality: nacional/estranger o lesionat/out
        	try{
        		TagNode imgStatus = tds[1+rowspan].getChildTags()[0];
        		if( "gif/nacional.gif".equals(imgStatus.getAttributeByName("src")) )
        			player.setNacionality("nacional.png");
        		if( "gif/extra.gif".equals(imgStatus.getAttributeByName("src")) )
        			player.setNacionality("extra.png");
        	}
        	catch(Exception e){}
        	
        	// td2, codi i nom del jugador
        	String codi = null;
        	String playerName = "";
        	try{
        		TagNode jugador = tds[2+rowspan].getChildTags()[0];
        		if( "a".equals(jugador.getName()) )
        		{
        			codi = jugador.getAttributeByName("href").
        				replace("http://www.acb.com/stspartidojug.php?cod_jugador=", "");
        			
        			List aChilds = jugador.getChildren();
        			TagNode fontJugador = (TagNode)aChilds.get(0);
        			List fChilds = fontJugador.getChildren();
        			playerName = ((ContentNode)fChilds.get(0)).toString();
        			
        			player.setCodi(codi);
        			player.setName(playerName);
        		}
        	}
        	catch(Exception e){}
        	
        	// td3, player info
        	try{
        		TagNode info = tds[3+rowspan].getChildTags()[0];
        		if( "a".equals(info.getName()) )
        		{
        			String sInfo = info.getAttributeByName("onmouseover").
        				replace("ddrivetip('", "").replace("')", "");
        			player.setInfo(sInfo);
        		}
        	}
        	catch(Exception e){}
        	
        	// td4, equip
        	try{
        		List equipChild = tds[4+rowspan].getChildren();
        		for( Object equipContent: equipChild )
        		{
        			if( equipContent instanceof ContentNode )
        			{
        				player.setTeam(equipContent.toString().trim());
        			}
        		}
        	}
        	catch(Exception e){}
        	
        	// td5, cost fitxatge i jornada del fitxatge
        	try{
        		List costChild = tds[5+rowspan].getChildren();
        		for( Object costContent: costChild )
        		{
        			if( costContent instanceof ContentNode )
        			{
        				Integer cost = Integer.valueOf(0);
	       				Integer buyDay = Integer.valueOf(0);
	       				Pattern p = Pattern.compile("([^\\s]*)\\s*(.*)$");
	       				Matcher m = p.matcher(costContent.toString().trim());
	       				if( m.find() ) 
	       				{
	       					try{
	       						cost = Integer.valueOf(nf.parse(m.group(1)).intValue());
	           				}catch(ParseException pe){
	           					cost = Integer.valueOf(0);
	           				}
	           				try{
	           					String tmpBuyDay = m.group(2).replace("(j&ordf;", "").replace(")", "");
	           					buyDay = Integer.valueOf(nf.parse(tmpBuyDay).intValue());
	           				}catch(ParseException pe){
	           					buyDay = Integer.valueOf(0);
	           				}
	       				}
	       				player.setCost(cost);
	       				player.setBuyDay(buyDay);
        			}
        		}
        	}
        	catch(Exception e){}

        	// td6, actual price
        	try{
        		List priceChild = tds[6+rowspan].getChildren();
        		for( Object priceContent: priceChild )
        		{
        			if( priceContent instanceof ContentNode )
        			{
        				Integer cost = Integer.valueOf(0);
        				try{
       						cost = Integer.valueOf(nf.parse(priceContent.toString()).intValue());
           				}catch(ParseException pe){
           					cost = Integer.valueOf(0);
           				}
        				player.setPrice(cost);
        			}
        		}
        	}
        	catch(Exception e){}

        	// td7, actual price
        	try{
        		List ratingChild = tds[7+rowspan].getChildren();
        		for( Object ratingContent: ratingChild )
        		{
        			if( ratingContent instanceof ContentNode )
        			{
        				Float rating = Float.valueOf(0);
        				try{
        					rating = Float.valueOf(nf.parse(ratingContent.toString()).floatValue());
           				}catch(ParseException pe){
           					rating = Float.valueOf(0);
           				}
        				player.setRating(rating);
        			}
        		}
        	}
        	catch(Exception e){}
        	
        	// td8, victory
        	try{
        		TagNode[] victoryChild = tds[8+rowspan].getChildTags();
        		for( TagNode victoryTag: victoryChild )
        		{
        			if( "font".equals(victoryTag.getName()) )
        				player.setVictory(true);
        		}
        	}
        	catch(Exception e){}
        
        	// td9, average rating
        	try{
        		List averageRatingChild = tds[9+rowspan].getChildren();
        		for( Object averageRatingContent: averageRatingChild )
        		{
        			if( averageRatingContent instanceof ContentNode )
        			{
        				Float averageRating = Float.valueOf(0);
        				try{
        					averageRating = Float.valueOf(nf.parse(averageRatingContent.toString()).floatValue());
           				}catch(ParseException pe){
           					averageRating = Float.valueOf(0);
           				}
        				player.setAverageRating(averageRating);
        			}
        		}
        	}
        	catch(Exception e){}
        	
        	// afegim el player a l'equip
        	team.addPlayer(position,player);
        }
        
        // cerquem javascript amb altres dades
        try
        {
        	Object[] tdsJS = node.evaluateXPath(TEAM_JAVASCRIPT_XPATH);
        	TagNode valsTd = (TagNode)tdsJS[2];
        	for( Object valsJSContent: valsTd.getChildren() )
        	{
        		if( valsJSContent instanceof ContentNode )
        		{
        			String[] vals = valsJSContent.toString().split("\n");
        			int tipus = 0;
        			for(String val: vals)
        			{
        				// saltem linies buides
        				if( "".equals(val.trim()) )
        					continue;
        				
        				// saltem linia function
        				if( "function muestra(valor)".equals(val.trim()) )
        					continue;
        				
        				// linies amb claus del javascript
        				if( "{".equals(val.trim()) || "}".equals(val.trim()) )
        					continue;
        				
        				// canvi de seccio de javascript
        				Pattern p = Pattern.compile("if \\(valor=='([^']*)'\\)");
	       				Matcher m = p.matcher(val.trim());
	       				if( m.find() ) 
	       				{
	       					if( "puntos".equals(m.group(1)) )
	       						tipus = 1;
	       					else if( "rebotes".equals(m.group(1)) )
	       						tipus = 2;
	       					else if( "triples".equals(m.group(1)) )
	       						tipus = 3;
	       					else if( "asistencias".equals(m.group(1)) )
	       						tipus = 4;
	       					
	       					// continuem a la seguent linia
	       					continue;
	       				}
	       				
	       				// exteiem els valors pel tipus en la posisio
	       				Pattern p2 = Pattern.compile("document.getElementById\\('val([^']*)'\\).innerHTML='([^']*)';document.getElementById\\('media([^']*)'\\).innerHTML='([^']*)';");
	       				Matcher m2 = p2.matcher(val.trim());
	       				if( m2.find() ) 
	       				{
	       					int pos = 0;
	        				try{
	        					pos = nf.parse(m2.group(1)).intValue();
	           				}catch(ParseException pe){
	           					pos = 0;
	           				}
	           				
	           				Integer value = Integer.valueOf(0);
	        				try{
	       						value = Integer.valueOf(nf.parse(m2.group(2)).intValue());
	           				}catch(ParseException pe){
	           					value = Integer.valueOf(0);
	           				}
	           				
           					Float average = Float.valueOf(0);
            				try{
            					average = Float.valueOf(nf.parse(m2.group(4)).floatValue());
               				}catch(ParseException pe){
               					average = Float.valueOf(0);
               				}
               				
               				switch(tipus)
               				{
               				case 1:
               					team.setPointsToPosition(value,average,pos);
               					break;
               				case 2:
               					team.setReboundsToPosition(value,average,pos);
               					break;
               				case 3:
               					team.setThreeToPosition(value,average,pos);
               					break;
               				case 4:
               					team.setAssistencesToPosition(value,average,pos);
               					break;
               				}
	       				}	
        			}
        			
        		}
        	}
        }
        catch(Exception e){}
		
		// parsejat ok
		Log.d(Supermanager.TAG, "MyTeamsParser: team list parsed ok");
		
		return System.nanoTime()-start;
	}
}
